//
//  UIImage.swift
//  
//
//  Created by tangbl93 on 2021/1/6.
//

import UIKit

// MARK: Ext
public extension UIImage {
    
    /// rendering with alwaysOriginal mode
    var yx_originalMode:UIImage {
        return self.withRenderingMode(.alwaysOriginal)
    }
    
    /// rendering with alwaysTemplate mode
    var yx_templateMode: UIImage {
        return self.withRenderingMode(.alwaysTemplate)
    }
    
    /// stretchable image; like chat bubble
    var yx_stretchableMode: UIImage {
        let leftCatpWidth = Int(self.size.width * 0.5)
        let topCapHeight = Int(self.size.height * 0.5)
        return self.stretchableImage(withLeftCapWidth: leftCatpWidth, topCapHeight: topCapHeight)
    }
    
    /// jpeg image base64 string
    func yx_jpegBase64(quality:CGFloat = 0.8, MIMEType:Bool = true) -> String {
        guard let jpegData = jpegData(compressionQuality: quality) else { return "" }
        if MIMEType {
            return "data:image/jpeg;base64," + jpegData.base64EncodedString()
        }
        return jpegData.base64EncodedString()
    }
    
    /// png image base64 string
    func yx_pngBase64(MIMEType:Bool = true) -> String {
        guard let pngData = pngData() else { return "" }
        if MIMEType {
            return "data:image/png;base64," + pngData.base64EncodedString()
        }
        return pngData.base64EncodedString()
    }
    
    /// resize image to new size
    func yx_resize(to size: CGSize) -> UIImage? {
        let renderer = UIGraphicsImageRenderer(size: size)
        return renderer.image { (context) in
            self.draw(in: CGRect(origin: .zero, size: size))
        }
    }
}

// MARK: Draw
public extension UIImage {
    
    /// draw water mask
    func yx_draw(waterMask image: UIImage?) -> UIImage {
        guard let image = image else { return self }
        
        defer { UIGraphicsEndImageContext() }
        
        let imageSize = self.size
        UIGraphicsBeginImageContextWithOptions(imageSize, false, UIScreen.main.scale)
        
        let waterMask: UIImage = image.yx_resize(to: imageSize) ?? image
        
        self.draw(at: CGPoint.zero)
        waterMask.draw(at: CGPoint.zero)
        
        return UIGraphicsGetImageFromCurrentImageContext() ?? self
    }
    
    /// draw pure color image
    func yx_draw(pureColor color: UIColor, size: CGSize = CGSize.yx_one) -> UIImage? {
        return color.yx_rending(size: size)
    }
}

// MARK: Write
public extension UIImage {
    
    typealias YXImageWriteToSavedPhotosAlbumHandler = ((Error?)->Void)
    
    private struct _YXAssociatedKeys {
        static var writeToSavedPhotosAlbum   = "writeToSavedPhotosAlbum"
    }
    
    /// write image to PhotosAlbum, need the following permissions:
    /// - NSLocationAlwaysAndWhenInUseUsageDescription
    /// - NSPhotoLibraryAddUsageDescription
    /// - NSPhotoLibraryUsageDescription
    func yx_writeToSavedPhotosAlbum(completeHandler: YXImageWriteToSavedPhotosAlbumHandler? = nil) {
        let closureWrapper = ClosureWrapper<YXImageWriteToSavedPhotosAlbumHandler>(closure: completeHandler)
        objc_setAssociatedObject(self, &_YXAssociatedKeys.writeToSavedPhotosAlbum, closureWrapper, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC);
        UIImageWriteToSavedPhotosAlbum(self, self, #selector(_yx_writeToSavedPhotosAlbum(_:didFinishSavingWithError:contextInfo:)), nil)
    }
    
    /// yx_writeToSavedPhotosAlbum handler
    @objc private func _yx_writeToSavedPhotosAlbum(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) {
        let closureWrapper = objc_getAssociatedObject(self, &_YXAssociatedKeys.writeToSavedPhotosAlbum) as? ClosureWrapper<YXImageWriteToSavedPhotosAlbumHandler>
        closureWrapper?.closure?(error)
    }
}
